//-------------------------------------------------------------------------
// File: Ip4.cpp
//
// Descr.: - todo -
//
// Author: Stefan Leihkauf
// Date:   23.03.2014
//-------------------------------------------------------------------------
#include "cb_pch.h"
#include "Ip4.h"
#include "common/util/Util.h"

namespace cb { namespace common { namespace net {

//-------------------------------------------------------------------------
Ip4::Ip4()
{
    _ip.value = 0L;
}

//-------------------------------------------------------------------------
Ip4::Ip4(uchar c0, uchar c1, uchar c2, uchar c3)
{
    this->set(c0, c1, c2, c3);
}

//-------------------------------------------------------------------------
Ip4::Ip4(ulong value)
{
    this->set(value);
}

//-------------------------------------------------------------------------
void Ip4::set(uchar c0, uchar c1, uchar c2, uchar c3)
{
    _ip.c0 = c0;
    _ip.c1 = c1;
    _ip.c2 = c2;
    _ip.c3 = c3;
}

//-------------------------------------------------------------------------
void Ip4::set(ulong value)
{
    _ip.value = value;
}

//-------------------------------------------------------------------------
void Ip4::set(const StdString& str)
{
    *this = Ip4::fromString(str);
}

//-------------------------------------------------------------------------
void Ip4::clear()
{
    memset(&_ip, 0, sizeof (_ip));
}

//-------------------------------------------------------------------------
bool Ip4::isEmpty() const
{
    return (*this == Ip4::Empty());
}

//-------------------------------------------------------------------------
std::string Ip4::toString() const
{
    std::stringstream ss;
    ss << static_cast<ulong>(_ip.c0) << "." <<
        static_cast<ulong>(_ip.c1) << "." <<
        static_cast<ulong>(_ip.c2) << "." <<
        static_cast<ulong>(_ip.c3);

    return ss.str();
}

//-------------------------------------------------------------------------
ulong Ip4::toULong() const
{
    return _ip.value;
}

//-------------------------------------------------------------------------
uchar& Ip4::operator [] (uint idx)
{
    assert(idx < 4);
    return ((uchar*)(&_ip.value))[idx];
}

//-------------------------------------------------------------------------
const uchar& Ip4::operator [] (uint idx) const
{
    assert(idx < 4);
    return ((uchar*)(&_ip.value))[idx];
}

//-------------------------------------------------------------------------
bool Ip4::operator ==(const Ip4& ip) const
{
    return (_ip.value == ip._ip.value);
}

//-------------------------------------------------------------------------
bool Ip4::operator !=(const Ip4& ip) const
{
    return !(*this == ip);
}

//-------------------------------------------------------------------------
Ip4 Ip4::fromString(const StdString& strIp)
{
    if (strIp.empty())
        return Ip4();

    // split ip string
    StringList strList = common::util::StringSplit(strIp, _T("."));
    if (strList.size() != 4)
        return Ip4();

    Ip4 ipRet;

    // check splitted string for sanity
    for (size_t i = 0; i < strList.size(); i++) {
        if (false == common::util::isIntegralNumber(strList[i]))
            return Ip4();

        ulong ipNum = common::util::StringToNumber<ulong>(strList[i]);

        /* it's surely not a ip if >255 */
        if (ipNum <= 255)
            ipRet[i] = static_cast<uchar>(ipNum);
        else
            return Ip4();
    }

    return ipRet;
}

//-------------------------------------------------------------------------
Ip4 Ip4::Empty()
{
    return Ip4(0L);
}

}}} // namespace